package com.medsoft.perfstat.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanMap;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.velocity.VelocityEngineFactoryBean;
import org.springframework.ui.velocity.VelocityEngineUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cyl.kernel.OutPacket;
import com.cyl.kernel.util.JsonUtils;
import com.medsoft.perfstat.pojo.AppSnap;
import com.medsoft.perfstat.pojo.AppSnapReq;
import com.medsoft.perfstat.pojo.ISGlobalStatus;
import com.medsoft.perfstat.pojo.ISGlobalVariable;
import com.medsoft.perfstat.pojo.OsInfo;
import com.medsoft.perfstat.pojo.SlaveStatus;
import com.medsoft.perfstat.pojo.Top10SQL;
import com.medsoft.perfstat.pojo.TopSlowQueryLogDigest;
import com.medsoft.perfstat.service.Constants;
import com.medsoft.perfstat.service.OverviewService;
import com.medsoft.perfstat.service.PerfStatCollectService;

/**
 * Created with IntelliJ IDEA. User: zjhua Date: 2015-01-02 Time: 23:56 Mail:
 * zjhua@hundsun.com Comment: 功能描述 Modifiy History: 修改历史 To change this template
 * use File | Settings | File Templates.
 */
@Controller
public class OverviewAction extends PerfStatBaseController {
	@Autowired
	private OverviewService overviewService;
	
	@Autowired
	private PerfStatCollectService perfStatCollectService;

	@RequestMapping(value = "/overview.html", method = RequestMethod.GET)
	public void index(Model model, HttpServletRequest request) {
		// NOP
	}
	
	@RequestMapping(value = "/validate_snap_interval.json", method = RequestMethod.GET)
	public @ResponseBody String validateSnapInterval(AppSnapReq req, Model model, HttpServletRequest request) {
		super.processReq(req);
		OutPacket out = new OutPacket();
		boolean isMysqlRestarted = overviewService.isMySQLRestarted(req);
		if(isMysqlRestarted) {
			out.setErrorInfo(-1, "两次快照时间MySQL重启过");
		}
		return JsonUtils.toJson(out);
	}
	
	@RequestMapping(value = "/json/create_snapshot.json", method = RequestMethod.POST)
	public @ResponseBody String createSnapshot(@RequestParam String appname,Model model, HttpServletRequest request) {
		OutPacket out = new OutPacket();
		try {
			perfStatCollectService.collectPerfStat(appname,0);
		} catch (Exception e) {
			out.setErrorInfo(-1, "创建快照出错，请查看服务器日志！");
			e.printStackTrace();
		}
		return JsonUtils.toJson(out);
	}

	@RequestMapping(value = "/overview.html", method = RequestMethod.POST)
	public String queryOverview(AppSnapReq req, Model model) {
		super.processReq(req);
		if (req.getAppname() == null
				|| req.getBeginSnapId() == null
				|| req.getEndSnapId() == null 
				|| Integer.parseInt(req.getBeginSnapId()) >= Integer.parseInt(req.getEndSnapId())) {
			model.addAttribute("errorCode","-1").addAttribute("errorInfo", "应用名称和快照起始号不能为空，且开始快照必须小于结束快照！");
			return "/error";
		}
		if(overviewService.isMySQLRestarted(req)) {
			model.addAttribute("errorCode","-1").addAttribute("errorInfo", "两次快照之间MySQL重启过！");
			return "/error";
		}
		
		Map<String, String> map = new BeanMap(req);

		List<ISGlobalVariable> headList = overviewService.queryHead(map);
		Map<String, String> headMap = new HashMap<String, String>();
		for (ISGlobalVariable item : headList) {
			headMap.put(item.getVariableName(), item.getVariableValue());
		}
		String[] begs = headMap.get("begin_cpu_time").trim().split(":");
		long beg = Long.valueOf(begs[0])*60+Long.valueOf(begs[1]);
		String[] ends = headMap.get("end_cpu_time").trim().split(":");
		long end = Long.valueOf(ends[0])*60+Long.valueOf(ends[1]);
		model.addAttribute("cpu_time", ((end-beg)/60 + ":" + (end-beg)%60));
		
		model.addAttribute("head", headMap);
		List<ISGlobalStatus> effList = overviewService.queryEfficiency(map);
		Map<String, String> effMap = new HashMap<String, String>();
		for (ISGlobalStatus item : effList) {
			effMap.put(item.getVariableName(), item.getVariableValue());
		}
		try {
			effMap.put("innodb_buffer_hit", String.valueOf(100 - Math
					.round(Double.parseDouble(effMap
							.get("Innodb_buffer_pool_reads".toUpperCase()))
							/ Double.parseDouble(effMap
									.get("Innodb_buffer_pool_read_requests"
											.toUpperCase())) * 100)));
			effMap.put("innodb_log_nowaits_hit", String.valueOf(100 - Math
					.round(Double.parseDouble(effMap.get("Innodb_log_waits"
							.toUpperCase()))
							/ Double.parseDouble(effMap
									.get("Innodb_log_write_requests"
											.toUpperCase())) * 100)));
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("Innodb_buffer_pool_reads:"
					+ effMap.get("Innodb_buffer_pool_reads".toUpperCase()));
			System.out.println("Innodb_buffer_pool_read_requests:"
					+ effMap.get("Innodb_buffer_pool_read_requests"
							.toUpperCase()));
			System.out.println("Innodb_log_write_requests:"
					+ effMap.get("Innodb_log_write_requests".toUpperCase()));
			System.out.println("Innodb_log_waits:"
					+ effMap.get("Innodb_log_waits".toUpperCase()));
		}
		
		List<OsInfo> osInfos = overviewService.queryOsInfo(map);
		if(osInfos.size() == 2) {
			model.addAttribute("osInfoBeg", osInfos.get(0));
			model.addAttribute("osInfoEnd", osInfos.get(1));
			headMap.put("cores".toUpperCase(), String.valueOf(osInfos.get(1).getCores()));
			double totalTimeElapse = (osInfos.get(1).getTotalTime() - osInfos.get(0).getTotalTime());
			model.addAttribute("avgSystemTime", String.valueOf(Math.round((osInfos.get(1).getSystemTime() - osInfos.get(0).getSystemTime())/totalTimeElapse*100)));
			model.addAttribute("avgUserTime", String.valueOf(Math.round((osInfos.get(1).getUserTime() - osInfos.get(0).getUserTime())/totalTimeElapse*100)));
			model.addAttribute("avgIoTime", String.valueOf(Math.round((osInfos.get(1).getIoTime() - osInfos.get(0).getIoTime())/totalTimeElapse*100)));
			model.addAttribute("avgTotalBusyTime", String.valueOf(Math.round((osInfos.get(1).getTotalBusyTime() - osInfos.get(0).getTotalBusyTime())/totalTimeElapse*100)));
		}
		
		model.addAttribute("efficiencyRate", effMap);
		
		model.addAttribute("top10eventdetail",
				overviewService.queryTop10EventDetail(map));
		
		model.addAttribute("top10event",
				overviewService.queryTop10EventSummary(map));
		
		List<Top10SQL> top10SQL = overviewService.queryTop10ElapsedSQL(map);
		double top10SQLSumTimer = 0.0;
		for(Top10SQL sql : top10SQL) {
			top10SQLSumTimer = top10SQLSumTimer+sql.getSumTimerWait();
		}
		for(Top10SQL sql : top10SQL) {
			sql.setSumTimerWaitPct(Math.round(sql.getSumTimerWait()/top10SQLSumTimer*100));
		}
		model.addAttribute("top10ElapsedSQL", top10SQL);
		
		List<Top10SQL> top10SQLRows = overviewService.queryTop10RowsExamSQL(map);
		double top10SQLSumRows = 0.0;
		for(Top10SQL sql : top10SQLRows) {
			top10SQLSumRows = top10SQLSumRows+sql.getSumRowsExamined();
		}
		for(Top10SQL sql : top10SQLRows) {
			sql.setSumRowsExaminedPct(Math.round(sql.getSumRowsExamined()/top10SQLSumRows*100));
		}
		model.addAttribute("top10RowsExamSQL", top10SQLRows);
		
		List<TopSlowQueryLogDigest> top10SlowSQL = overviewService.queryTopSlowQueryLogDigest(map);
		double top10SlowSQLSum = 0.0;
		for(TopSlowQueryLogDigest sql : top10SlowSQL) {
			top10SlowSQLSum = top10SlowSQLSum+sql.getTotalResponseTime();
		}
		for(TopSlowQueryLogDigest sql : top10SlowSQL) {
			sql.setTotalResponseTimePct((int)Math.round(sql.getTotalResponseTime()/top10SlowSQLSum*100));
		}
		model.addAttribute("top10SlowSQL", top10SlowSQL);
		
		
		model.addAttribute("criticalStatus",
				overviewService.queryCriticalStatus(map));
		model.addAttribute("criticalVariables",
				overviewService.queryCritialVariales(map));
		model.addAttribute("top10TableIOWait",
				overviewService.queryTop10TableIOWait(map));
		model.addAttribute("top10IndexIOWait",
				overviewService.queryTop10IndexIOWait(map));
		model.addAttribute("top10TableRowsRead",
				overviewService.queryTop10TableRowsRead(map));
		model.addAttribute("top10IndexRowsRead",
				overviewService.queryTop10IndexRowsRead(map));
		model.addAttribute("perfSchema", overviewService.queryPerfSchema(map));
		model.addAttribute("slaveVariable",
				overviewService.querySlaveVariables(map));
		List<SlaveStatus> list = overviewService.querySlaveInfo(map);
		if(list == null || list.size() == 0) {
			model.addAttribute("slaveStatus",new HashMap<String,String>());
		} else {
			model.addAttribute("slaveStatus",new BeanMap(list.get(0)));
		}
		model.addAttribute("galeraClusterVariables",
				overviewService.queryGaleraClusterVariales(map));
		model.addAttribute("galeraClusterInfo",
				overviewService.queryGaleraClusterInfo(map));
		return "/overview";
	}

	@RequestMapping(value = "/json/query_snap_id_flagment.json", method = RequestMethod.GET)
	public @ResponseBody String querySnapIdByAppname(
			@RequestParam String appname, HttpServletRequest request) {
		List<AppSnap> list = overviewService.querySnapIdByAppname(appname);
		Map<String, Object> ctx = new HashMap<String, Object>();
		ctx.put("appSnaps", list);
		String result = VelocityEngineUtils.mergeTemplateIntoString(super
				.getVelocityConfigurer().getVelocityEngine(),
				Constants.FLAGMENT_PATH + "snap_id_select_option.vm", "GBK",
				ctx);
		return result;
	}
}
